package com.xunhang.service.impl;

import com.xunhang.entity.News;
import com.xunhang.entity.Type;
import com.xunhang.repository.NewsRepository;
import com.xunhang.repository.TypeRepository;
import com.xunhang.service.peoService;
import com.xunhang.utils.HtmlParser;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.concurrent.TimeUnit;


@Service
public class peoServiceImpl implements peoService {

    @Autowired
    private NewsRepository newsRepository;

    @Autowired
    private TypeRepository typeRepository;

    // 基础URL用于处理相对路径
    private static final String BASE_URL = "https://news.whu.edu.cn";

    @Override
    @Transactional
    public void crawlSingleNews(String listUrl) throws IOException {
        try {
            int currentPage = 0; // 默认首页没有页码

            // 如果URL是首页，设置当前页为0
            if (listUrl.equals("https://news.whu.edu.cn/ljrw.htm")) {
                currentPage = 0;
            }
            // 如果URL是分页，解析当前页码
            else if (listUrl.matches("https://news.whu.edu.cn/ljrw/\\d+\\.htm")) {
                String pageStr = listUrl.replaceAll(".*/(\\d+)\\.htm$", "$1");
                currentPage = Integer.parseInt(pageStr);
            }

            boolean foundNewNews = false;

            do {
                Document listPage = getDocumentWithRetry(listUrl, 3);
                Elements newsItems = listPage.select("ul.wdzxList > li[id^='line_u']");

                for (Element newsItem : newsItems) {
                    News parsedNews = HtmlParser.parseNewsItem(newsItem);
                    String newsTitle = parsedNews.getTitle();

                    if (!newsRepository.existsByTitle(newsTitle)) {
                        processNewsItem(newsItem, listUrl);
                        System.out.println("新增新闻: " + newsTitle);
                        foundNewNews = true;
                        return; // 找到一条新新闻后即返回
                    } else {
                        System.out.println("新闻已存在: " + newsTitle);
                    }
                }

                System.out.println("当前页没有新新闻，尝试下一页...");

                currentPage++;

                // 首页的特殊处理
                if (currentPage == 1) {
                    listUrl = "https://news.whu.edu.cn/ljrw/15.htm";
                } else {
                    int nextPageNum = 15 - (currentPage - 1);
                    listUrl = String.format("https://news.whu.edu.cn/ljrw/%d.htm", nextPageNum);
                }

                // 防止无限循环，设置最大翻页次数
                if (currentPage > 15) { // 假设最多翻50页
                    System.out.println("不再爬取更早时间的新闻");
                    break;
                }

            } while (!foundNewNews);

        } catch (Exception e) {
            throw new IOException("抓取单条新闻失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional
    public void crawlBatchNews(String listUrl, int maxCount) throws IOException {
        try {
            int currentPage = parsePageNumber(listUrl);
            int addedCount = 0;
            int remainingCount = maxCount; // 新增：记录剩余需要抓取的数量

            while (remainingCount > 0 && currentPage <= 10) { // 修改循环条件
                System.out.printf("正在抓取第%d页，还需%d条新闻%n", currentPage, remainingCount);

                Document listPage = getDocumentWithRetry(listUrl, 3);
                Elements newsItems = listPage.select("ul.wdzxList > li[id^='line_u']");

                // 处理当前页新闻（优先处理未抓取的）
                for (Element newsItem : newsItems) {
                    if (remainingCount <= 0) break; // 关键修改：严格剩余数量控制

                    News parsedNews = HtmlParser.parseNewsItem(newsItem);
                    if (!newsRepository.existsByTitle(parsedNews.getTitle())) {
                        processNewsItem(newsItem, listUrl);
                        addedCount++;
                        remainingCount--; // 每新增一条就减少剩余数量
                        System.out.printf("新增新闻[%d/%d]: %s%n",
                                addedCount, maxCount, parsedNews.getTitle());
                    }
                }

                // 提前退出条件
                if (remainingCount <= 0) break;

                // 准备下一页
                currentPage++;
                if (currentPage > 10) {
                    System.out.println("不再爬取更早时间的新闻");
                    break;
                }
                listUrl = getNextPageUrl(currentPage);
                Thread.sleep(1000);
            }

            System.out.printf("操作完成，实际新增%d/%d条新闻%n", addedCount, maxCount);
        } catch (Exception e) {
            throw new IOException("批量抓取失败: " + e.getMessage(), e);
        }
    }



    // 解析当前页码
    private int parsePageNumber(String url) {
        if (url.equals("https://news.whu.edu.cn/ljrw.htm")) {
            return 0;
        } else if (url.matches(".*/ljrw/\\d+\\.htm")) {
            String num = url.replaceAll(".*/(\\d+)\\.htm$", "$1");
            return 15 - Integer.parseInt(num) + 1;
        }
        return 0;
    }

    // 生成下一页URL
    private String getNextPageUrl(int currentPage) {
        if (currentPage == 1) {
            return "https://news.whu.edu.cn/ljrw/15.htm";
        } else {
            int pageNum = 15 - (currentPage - 1);
            return String.format("https://news.whu.edu.cn/ljrw/%d.htm", pageNum);
        }
    }

    /**
     * 处理单个新闻条目
     */
    private void processNewsItem(Element item, String refererUrl) throws IOException {
        News news = HtmlParser.parseNewsItem(item);
        news.setSource("武汉大学新闻网");
        //  news.setType("武大要闻");
        System.out.println("[DEBUG] 解析到新闻条目: " + news.getTitle() + ", URL: " + news.getDetailUrl()); // 添加

        if (news.getDetailUrl() == null) {
            System.out.println("[WARN] 新闻URL为空，跳过"); // 添加
            return;
        }

        try {
            Document detailPage = Jsoup.connect(news.getDetailUrl())
                    .referrer(refererUrl)
                    .get();
            System.out.println("[DEBUG] 成功获取详情页: " + news.getDetailUrl()); // 添加

            HtmlParser.parseNewsDetail(detailPage, news);

            if (isValidNews(news)) {
                System.out.println("[DEBUG] 准备保存新闻: " + news.getTitle()); // 添加
                newsRepository.save(news);
                News savedNews = newsRepository.save(news);
                System.out.println("[SUCCESS] 已保存到数据库: " + news.getTitle()); // 添加


            } else {
                System.out.println("[WARN] 新闻校验失败: " + news.getTitle()); // 添加
            }
        } catch (IOException e) {
            System.err.println("[ERROR] 处理新闻失败: " + news.getTitle() + ", URL: " + news.getDetailUrl());
            throw e;
        }
    }



    /**
     * 处理相对URL
     */
    private String resolveRelativeUrl(String url) {
        if (url == null) return null;
        if (url.startsWith("http")) return url;
        if (url.startsWith("../")) url = url.substring(2);
        return BASE_URL + "/" + url;
    }

    /**
     * 处理图片URL
     */
    private String resolveImageUrl(String imgUrl) {
        if (imgUrl == null) return "";
        if (imgUrl.startsWith("/__local/")) {
            return BASE_URL + imgUrl;
        }
        return imgUrl;
    }

    /**
     * 带重试机制的请求
     */
    private Document getDocumentWithRetry(String url, int maxRetry) throws IOException {
        IOException lastException = null;
        for (int i = 0; i < maxRetry; i++) {
            try {
                return Jsoup.connect(url)
                        .userAgent("Mozilla/5.0")
                        .timeout(10000)
                        .get();
            } catch (IOException e) {
                lastException = e;
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        throw lastException;
    }

    /**
     * 验证新闻数据有效性
     */
    private boolean isValidNews(News news) {
        return news.getTitle() != null && !news.getTitle().isEmpty()
                && news.getDetail() != null && !news.getDetail().isEmpty();
    }
}